package edu.mit.simile;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.hp.hpl.jena.ontology.OntDocumentManager;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.ontology.Ontology;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.shared.PrefixMapping;
import com.hp.hpl.jena.util.FileManager;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;

public class ModelLoader {
                
                
        private Model inputModel = null ;
        private Model contextModel = null ;
        
        private Model outputModel = null ;
        
        private List<Rule> rules = null ;
        
        
        private OntModel ensModel = null;
        
        private static String baseUri = null;
        
        private Properties prop = null ;
        
        String inputDatasetFileName = "" ;
        private String outputDatasetFileName = "" ;
        private String rulesFileName = "" ;
        String inputContextFileName="";
        
        
        /** Creates a new instance of ModelLoader (singleton) */
        private static final ModelLoader loader = new ModelLoader();
        /** Private constructor */
        private ModelLoader() {
                prop = new Properties();
            try {
            //load a properties file
                 prop.load(new FileInputStream("config/rdf2okkam.properties"));
                 inputDatasetFileName=prop.getProperty("inputDatasetFileName");
                 outputDatasetFileName=prop.getProperty("outputDatasetFileName");
                 inputContextFileName=prop.getProperty("inputContextFileName");
                 rulesFileName=prop.getProperty("rulesFileName");

         } catch (IOException ex) {
                 ex.printStackTrace();
                 System.out.println("File not found");
     }
                
                loadInputModel() ;
                loadContextModel();
                loadOutputModel() ;
                loadRules() ;                
                
        }
        
         
        
        private static Log log = LogFactory.getLog(ModelLoader.class);
        
        /** Acces the static instance of wife */
    public static ModelLoader getInstance(){

            return loader;
    }
        
        private void loadInputModel(){
                
                // use the FileManager to find the input file
                InputStream in = FileManager.get().open( inputDatasetFileName );
                if (in == null) {                    
                        log.error("File: " + inputDatasetFileName + " not found");
                        System.exit(0);
                }
                
                // Create the input model. Models different from the default one import also the 
                // rdf and rdf-schema axioms. The input model usually comes with blank nodes. 
                inputModel = ModelFactory.createDefaultModel();
                
                // read the RDF/TURTLE file
                inputModel.read(in, baseUri, "TURTLE");
                
                
                
        }
        
        private void loadContextModel(){
                
                // use the FileManager to find the input file
                InputStream in = FileManager.get().open( inputContextFileName );
                if (in == null) {                    
                        log.error("File: " + inputContextFileName + " not found");
                        System.exit(0);
                }
                
                // Create the input model. Models different from the default one import also the 
                // rdf and rdf-schema axioms. The input model usually comes with blank nodes. 
                contextModel = ModelFactory.createDefaultModel();
                
                // read the RDF/TURTLE file
                contextModel.read(in, baseUri, "TURTLE");
                
                
                
        }
        private void loadOutputModel(){
                
                
                 // use the FileManager to find the input file
                InputStream out = FileManager.get().open( outputDatasetFileName );
                if (out == null) {                    
                        log.error("File: " + outputDatasetFileName + " not found");
                        System.exit(0);
                }
                
                // Create the input model. Models different from the default one import also the 
                // rdf and rdf-schema axioms. The input model usually comes with blank nodes. 
                outputModel = ModelFactory.createDefaultModel();
                
                // read the RDF/TURTLE file
                
                //outputModel.read(out, baseUri, "TURTLE");
                
                // Create the output model. No blank nodes allowed here.
                outputModel = ModelFactory.createDefaultModel() ;        
                
                PrefixMapping prefix = PrefixMapping.Factory.create() ;
                String ensNS = "http://models.okkam.org/ENS-core-vocabulary.owl#" ;
                String ensPrefix = "ens" ;
                
                prefix.setNsPrefix(ensPrefix, ensNS) ;
                
                outputModel.setNsPrefixes(prefix) ;
                
        }
        
        private void loadRules() {
                //Load the mapping rules
                BufferedReader in = null ;
                try {
                        
                        in = new BufferedReader( new FileReader( rulesFileName ) );
                }
                catch(FileNotFoundException fnfe) {
                        log.info( fnfe.getMessage() ) ;
                }
                
                if( in != null ) {
                        
                        rules = Rule.parseRules( Rule.rulesParserFromReader(in) );
                        
                }
                else {
                        log.warn( "No rules in " + rulesFileName );
                }

                
        }
        
        public Model getInputModel() {
                return inputModel ;
        }
        
        public Model getContextModel() {
                return contextModel ;
        }
        
        public Model getOutputModel() {
                return outputModel ;
        }
        
        public List<Rule> getRules() {
                return rules ;
        }
        
        public void writeOutputModel(Model outputModel) {
                
                OutputStream out = null;
                try {
                        out = new FileOutputStream(new File(outputDatasetFileName));
                } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        log.error("File: " + outputDatasetFileName + " not found");
                        System.exit(0);
                        e.printStackTrace();
                }
                this.outputModel=outputModel;
                this.outputModel.write(out, "TRIG") ;
                
        }
}